package main

import (
	"crypto/rand"
	"fmt"
	"log"
	"math/big"
)

func main() {
	// rand.Int:

	// Generat a random integer using rand.Int and passing it a rand.Reader
	// as it's generator and a *big.Int as it's max value to return
	//
	// Reader is a global, shared instance of a cryptographically
	// strong pseudo-random generator.
	//
	// On Unix-like systems, Reader reads from /dev/urandom.
	// On Linux, Reader uses getrandom(2) if available, /dev/urandom otherwise.
	// On Windows systems, Reader uses the CryptGenRandom API.
	n, err := rand.Int(rand.Reader, big.NewInt(10))
	if err != nil {
		log.Fatalln("rand.Int error:", err)
	}

	// Print out the random number generated from rand.Int
	fmt.Println(n)

	fmt.Println()

	// rand.Prime:

	// Prime returns a number, p, of the given size, such that p is prime
	// with high probability.
	// Prime will return error for any error returned by rand.Read or if bits < 2.
	p, err := rand.Prime(rand.Reader, 99)
	if err != nil {
		log.Fatalln("rand.Prime error:", err)
	}

	// Print out integer p generated from rand.Prime
	fmt.Printf("%d\n", p)

	fmt.Println()

	// Read:

	// Create a new []byte `b` of size 10 bytes which rand.Read will
	// fill with 10 random bytes when rand.Read(b) is called
	b := make([]byte, 10)

	// Read is a helper function that calls Reader.Read using io.ReadFull.
	// On return, n == len(b) if and only if err == nil.
	_, err = rand.Read(b)
	if err != nil {
		log.Fatalln("rand.Read error", err)
	}

	// Print out the random bytes stored in `b`, generated by calling
	// rand.Read and passing it `b` as it's parameter
	//
	// B now contains random bytes intead of only zeros
	// from initialization
	fmt.Printf("%x\n", b)
}
